#include "ros/ros.h"
#include "festival/utils.h"
#include "festival/snprintf.h"
#include "festival/Voice.h"

// This function executes a command through Festival's command line interface.
// The command should be written in Scheme format. (See http://festvox.org/docs/manual-1.4.3/festival_8.html#SEC21)
// NOTE: It is the responsibility of the calling function to close the file handle.
FILE* execFestivalCmd(const char *cmd) {
  char *cmdComplete;
  if (asprintf(&cmdComplete, cmdFestivalBase, cmd) >= 0) {
    ROS_DEBUG("%s\n", cmdComplete);
    return popen(cmdComplete, "r");
  }
  
  return NULL;
}

bool updateFestivalVoiceSet(std::vector<festival::Voice>* p_voiceSet) {
  FILE *p_stdOutput = execFestivalCmd(cmdFestivalVoiceList);
  
  // Check that the command returned a valid file pointer
  if (p_stdOutput == NULL) {
    ROS_ERROR("Error reading Festival console output");
    return false;
  } else {
    // If a voice set exists, clear it
    if (p_voiceSet->size() > 0)
      p_voiceSet->clear();
    
    // Initialize buffers
    int c;
    std::string buf;
    
    // Parse the console output
    do {
      c = getc(p_stdOutput);
      
      // Ignore opening and closing parentheses
      if (c == '(' || c == ')') {
        continue;
      
      // When a space is found, append current string buffer to voice set and continue
      } else if (c == ' ') {
        festival::Voice new_voice;
        new_voice.name = buf;
        p_voiceSet->push_back(new_voice);
        buf = "";
      
      // Append new char to string buffer
      } else {
        buf += (char)c;
      }
        
    } while (c != EOF);
  }
  
  pclose(p_stdOutput);
  
  ROS_INFO("Found %d available voices for Festival:", p_voiceSet->size());
  
  std::vector<festival::Voice>::iterator it;
  for (it = p_voiceSet->begin(); it != p_voiceSet->end(); ++it)
    ROS_INFO("  %s", (*it).name.c_str());
  
  return true;
}
